package unipampa.games.pampaPife{
	import com.smartfoxserver.v2.SmartFox;
	import com.smartfoxserver.v2.core.SFSEvent;
	import com.smartfoxserver.v2.entities.User;
	import com.smartfoxserver.v2.entities.data.ISFSArray;
	import com.smartfoxserver.v2.entities.data.ISFSObject;
	import com.smartfoxserver.v2.entities.data.SFSObject;
	import com.smartfoxserver.v2.requests.*;
	
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	
	import unipampa.games.pampaPife.Carta;
	
	public class PampaPifeGame extends Sprite{
		
		[Embed('../assets/mesaAssets3.swf', symbol='mainStage')]
		private var MainStage:Class;
		private var mainMC:Sprite;
		private var sfs:SmartFox;
		
		private var cartasMC:MovieClip;
		private var cartaMonteMC:MovieClip;
		private var cartaDescarteMC:MovieClip;
		private var mensagemMC:MovieClip;
		private var botaoBaterMC:MovieClip;
		private var cartasGanhadorMC:MovieClip;
		
		private var extensionName:String;
		private var container:Object;
		private var jogoIniciado:Boolean;
		private var gameStarted:Boolean;
		private var iAmSpectator:Boolean;
		
		private var jogadorDaVez:int;
		private var nplayers:int;
		private var nomesJogadores:Array;
		private var cartas:Array;
		private var cartaSelecionada:int;
		private var cartaDoMonte:Carta;
		private var cartaDoDescarte:Carta;
		/** Função que cria a instância do jogo */
		public  function PampaPifeGame(){
			mainMC = new MainStage();
			extensionName = "PampaPife";
		}
		/** Função que inicializa algumas variáveis do jogo e mostra a mensagem
		 *  de espera do início do jogo de forma diferente para o dono da sala 
		 *  e para os outros jogadores. */
		public  function initGame(params:Object = null):void{
			if (params != null){
				container = params.container;
				jogoIniciado = false;
				
				sfs = params.sfs;
				sfs.addEventListener(SFSEvent.EXTENSION_RESPONSE, onExtensionResponse);
				/* Inicializando a parte gráfica do jogo. */
				addChild(mainMC);
				cartaMonteMC    = mainMC.getChildByName("monte") as MovieClip;
				cartaDescarteMC = mainMC.getChildByName("descarte") as MovieClip;
				botaoBaterMC    = mainMC.getChildByName("bater") as MovieClip;
				mensagemMC      = mainMC.getChildByName("mensagem") as MovieClip;
				cartasGanhadorMC = mainMC.getChildByName("cartasGanhador") as MovieClip;
				/* Configurando a imagem a ser mostrada para o monte e o descarte. */
				cartaMonteMC.gotoAndStop("verso");
				cartaDescarteMC.gotoAndStop("vazio");
				cartasGanhadorMC.visible=false;
				resetCartas();
				
				iAmSpectator = (sfs.mySelf.playerId == -1);
					
				/* Mostrando a mensagem de espera. */
				var message:String;
				if (sfs.mySelf.playerId!=1){ /* Mensagem dos jogadores. */
					message = "Esperando início\ndo Jogo";
					if (!iAmSpectator){
						container.showGamePopUp("wait", message, null)
						sfs.send( new ExtensionRequest("pronto", new SFSObject(), sfs.lastJoinedRoom) )
					}
				}
				else{
					message = "Iniciar jogo"; /* Mensagem para o dono da sala. */
					container.showGamePopUp("waitOwner", message, pedeInicioPartida)
				}
			}
			else
				trace("Erro inesperado: parâmetros não comtém os dados necessários!")
		}
		/** Função executada quando o dono da sala clica no botão iniciar. Envia uma mensagem
		 *  ao servidor que então manda o comando "start" para todos os jogadores. */
		private function pedeInicioPartida():void{
			sfs.send( new ExtensionRequest("iniciar", new SFSObject(), sfs.lastJoinedRoom) )
		}
		/** Função que é executada ao receber o comando "start" do servidor. 
		 *  Inicializa as variáveis de cada jogador e envia pedido de cartas
		 *  para o servidor. */
		private function iniciarJogo(params:ISFSObject):void{
			var nomesIdsStr:String = ("p1n","p2n","p3n","p4n","p5n","p6n","p7n","p8n","p9n","p10n");
			nomesJogadores = new Array();
			cartas = new Array();
			cartaDoMonte = new Carta();
			cartaDoDescarte = new Carta();
			cartaSelecionada = -1;
			//resetCartas();
			/* Remove popup da mensagem de espera */
			container.removeGamePopUp();
			
			jogadorDaVez = params.getInt("t");
			nplayers = params.getInt("nplayers");
			
			//for (var i:int = 0; i<nplayers; i++ ){
			//	nomesJogadores[i] = new String(params.getUtfString(nomesIdsStr[i]).toString());
			//}
			
			sfs.send( new ExtensionRequest("cartas", new SFSObject(), sfs.lastJoinedRoom) );
		}
		/** Função executada quando se recebe o comando "cartas", tratando o objeto
		 *  enviado do servidor e extraindo e armazenado os valores das cartas do jogador. */
		private function recebeCartas(params:ISFSObject):void{
			var cartasStr:Array = ["c1","c2","c3","c4","c5","c6","c7","c8","c9"];
			var cartasStrCmp:Array = ["v","n","b"];
			var valor:int;
			var naipe:int;
			var baralho:int;
						
			for (var i:int = 0; i < 9; i++){
				valor = params.getInt(cartasStr[i]+cartasStrCmp[0]);
				naipe = params.getInt(cartasStr[i]+cartasStrCmp[1]);
				baralho = params.getInt(cartasStr[i]+cartasStrCmp[2]);
				cartas[i] = new Carta(valor, naipe, baralho);
				var carta_sel:MovieClip = mainMC.getChildByName("carta"+i) as MovieClip;
				carta_sel.gotoAndStop((naipe+1)+"-"+(valor+1));
			}
			ativarCartas();
		}
		/** Função executada quando recebe do servidor a carta comprada do monte. */
		private function recebeCartaDoMonte(params:ISFSObject):void{
			var valor:int = params.getInt("valor");
			var naipe:int = params.getInt("naipe");
			var baralho:int = params.getInt("baralho");
			var msg:TextField = mensagemMC.texto as TextField;
			
			msg.text = "Selecione a carta a ser descartada.";
			cartaMonteMC.gotoAndStop((naipe+1)+"-"+(valor+1));
			cartaDoMonte.setCarta(valor, naipe, baralho);
		}
		/** Função que ativa ou desativa o monte de compra ou de descarte conforme 
		 *  o jogador da vez. Somente habilita os botões se for a vez do jogador. */
		private function setTurno():void{
			if (sfs.mySelf.playerId == jogadorDaVez){ 
				cartaMonteMC.buttonMode = true;
				cartaMonteMC.removeEventListener(MouseEvent.CLICK, descartaDoMonte);
				cartaMonteMC.addEventListener(MouseEvent.CLICK,compraDoMonte );
				botaoBaterMC.buttonMode = true;
				botaoBaterMC.addEventListener(MouseEvent.CLICK,bater );
				if (cartaDescarteMC.currentLabel != "vazio"){ /* se existe carta no descarte */
					cartaDescarteMC.buttonMode = true;
					cartaDescarteMC.addEventListener(MouseEvent.CLICK,compraDoDescarte );
				}
			}
			else{
				cartaMonteMC.buttonMode = false;
				cartaDescarteMC.buttonMode = false;
				botaoBaterMC.buttonMode = false;
			}
		}
		/** Função para ativar a função de botão das cartas. */
		private function ativarCartas():void{
			setTurno();
			for (var i:int = 0; i < 9; i++){
				var carta_sel:MovieClip = mainMC.getChildByName("carta"+i) as MovieClip;
				carta_sel.buttonMode = true; /* Ativando a função de botão */
				carta_sel.addEventListener(MouseEvent.CLICK,selecionaCarta );/* Adicioando evento de mouse */
				carta_sel.y = 330; /* setando a posição vertical */
			}
		}
		/** Função para desativar a função de botão das cartas. */
		private function desativarCartas():void{
			cartaDescarteMC.buttonMode = false;
			cartaDescarteMC.removeEventListener(MouseEvent.CLICK,compraDoDescarte );
			cartaMonteMC.buttonMode = false;
			cartaMonteMC.removeEventListener(MouseEvent.CLICK, descartaDoMonte );
			cartaMonteMC.removeEventListener(MouseEvent.CLICK, compraDoMonte );
			botaoBaterMC.buttonMode = false;
			botaoBaterMC.removeEventListener(MouseEvent.CLICK,bater );
			for (var i:int = 0; i < 9; i++){
				var carta_sel:MovieClip = mainMC.getChildByName("carta"+i) as MovieClip;
				carta_sel.buttonMode = false;
				carta_sel.removeEventListener(MouseEvent.CLICK,selecionaCarta );
			}
		}
		/** Função executada quando o jogador sai da sala. */
		public  function destroyGame(params:Object = null):void {
			sfs.removeEventListener(SFSEvent.EXTENSION_RESPONSE, onExtensionResponse)
		}
		/** Função utilizada para setar as cartas antes do início do jogo. */
		private function resetCartas():void{
			for (var i:int = 0; i < 9; i++){
				var carta_sel:MovieClip = mainMC.getChildByName("carta"+i) as MovieClip;
				carta_sel.gotoAndStop("verso");
			}
		}
		/** Função que movimenta as cartas para cima quando elas são selecionadas. */ 
		private function moveCarta(indice:int):void{
			var carta_sel:MovieClip = mainMC.getChildByName("carta"+indice) as MovieClip;

			if (carta_sel.y == 330)
				carta_sel.y = 320;
			else 
				carta_sel.y = 330;
		}
		/** Função que troca duas cartas de lugar ou troca uma carta com a carta comprada. */
		private function trocaCartas(c1:int, c2:int):void{
			var cartaTemp:Carta = new Carta();
			cartaTemp.setCarta(cartas[c1].Valor(),cartas[c1].Naipe(),cartas[c1].Baralho());
			var carta_sel:MovieClip;
			if (c2 < 9) {
				cartas[c1].setCarta(cartas[c2].Valor(),cartas[c2].Naipe(),cartas[c2].Baralho());
				cartas[c2].setCarta(cartaTemp.Valor(),cartaTemp.Naipe(),cartaTemp.Baralho());

				carta_sel = mainMC.getChildByName("carta"+c1) as MovieClip;
				carta_sel.gotoAndStop((cartas[c1].Naipe()+1)+"-"+(cartas[c1].Valor()+1));
				carta_sel = mainMC.getChildByName("carta"+c2) as MovieClip;
				carta_sel.gotoAndStop((cartas[c2].Naipe()+1)+"-"+(cartas[c2].Valor()+1));
			}
			else{ /* troca com o Monte ou com o Descarte */
				desativarCartas();
				cartaSelecionada = -1;
				/* Montando a resporta para o servidor */
				var respObj:SFSObject = new SFSObject();
				respObj.putInt("valor",cartas[c1].Valor());
				respObj.putInt("naipe",cartas[c1].Naipe());
				respObj.putInt("baralho",cartas[c1].Baralho());
				carta_sel = mainMC.getChildByName("carta"+c1) as MovieClip;
				/* Trocando as cartas */
				switch (c2){
					case 10: // Monte
						cartas[c1].setCarta(cartaDoMonte.Valor(),cartaDoMonte.Naipe(),cartaDoMonte.Baralho());
						carta_sel.gotoAndStop(cartaMonteMC.currentFrame);
						cartaMonteMC.gotoAndStop("verso");
						break;
					case 11: // Descarte
						cartas[c1].setCarta(cartaDoDescarte.Valor(),cartaDoDescarte.Naipe(),cartaDoDescarte.Baralho());
						carta_sel.gotoAndStop((cartas[c1].Naipe()+1)+"-"+(cartas[c1].Valor()+1));
						cartaDescarteMC.gotoAndStop("verso");
						break;
				}
				/* Enviando carta para descarte. */
				sfs.send( new ExtensionRequest("descartarCarta", respObj, sfs.lastJoinedRoom) );
			}
		}
		/** Função que seleciona as cartas para fazer a troca entre elas. */
		private function selecionaCarta(evt:MouseEvent):void{
			var carta_sel:MovieClip = evt.target as MovieClip;
			var carta:int = parseInt(carta_sel.name.substr(5,1));
			var msg:TextField = mensagemMC.texto as TextField;
				
			if ( cartaSelecionada == -1 ){ /* se não tem carta selecionada */
				cartaSelecionada = carta;
				moveCarta(carta);
				msg.text = "Selecione outra carta para trocar.";
			}
			else{ /* Se já houver uma carta selecionada então troca cartas de lugar. */
				msg.text = "";
				trocaCartas(carta,cartaSelecionada);
				if (cartaSelecionada < 10){ /* Se a carta selecionada não é do monte o do descarte. */
					moveCarta(cartaSelecionada);
				}
				cartaSelecionada = -1;
			}
		}
		/** Função executada quando o botão do monte é clicado, 
		 *  enviando solicitação de compra do monte. */
		private function compraDoMonte(evt:MouseEvent):void{
			cartaSelecionada = 10;
			cartaMonteMC.buttonMode = false;
			cartaMonteMC.removeEventListener(MouseEvent.CLICK,compraDoMonte);
			cartaMonteMC.addEventListener(MouseEvent.CLICK, descartaDoMonte);
			sfs.send( new ExtensionRequest("comprarDoMonte", new SFSObject(), sfs.lastJoinedRoom) );
		}
		/** Função executada quando o botão do monte tem o evento de descarte da carta que se 
		 *  comprou do monte. *//**/
		private function descartaDoMonte(evt:MouseEvent):void{
			desativarCartas();
			cartaMonteMC.removeEventListener(MouseEvent.CLICK, descartaDoMonte);
			cartaSelecionada = -1;
			cartaMonteMC.gotoAndStop("verso");
			
			var respObj:SFSObject = new SFSObject();
			respObj.putInt("valor",cartaDoMonte.Valor());
			respObj.putInt("naipe",cartaDoMonte.Naipe());
			respObj.putInt("baralho",cartaDoMonte.Baralho());
			
			/* Enviando carta para descarte. */
			sfs.send( new ExtensionRequest("descartarCarta", respObj, sfs.lastJoinedRoom) );
		}
		/** Função executada quando o botão do descarte é clicado,
		 *  enviando solicitação de compra do descarte. */
		private function compraDoDescarte(evt:MouseEvent):void{
			cartaSelecionada = 11;
			cartaDescarteMC.buttonMode = false;
			var msg:TextField = mensagemMC.texto as TextField;
			msg.text = "Selecione a carta a ser descartada.";
			sfs.send( new ExtensionRequest("comprarDoDescarte", new SFSObject(), sfs.lastJoinedRoom) );
		}
		/** Função ativada pelo botaoBater. 
		 *  Envia as cartas para o servidor para validar os jogos. */
		private function bater(evt:MouseEvent):void{
			var cartasStr:Array = ["c1","c2","c3","c4","c5","c6","c7","c8","c9"];
			var cartasStrCmp:Array = ["v","n","b"];
			
			var respObj:SFSObject = new SFSObject();
			for (var i:int = 0; i < 9; i++){
				respObj.putInt(cartasStr[i]+cartasStrCmp[0],cartas[i].Valor());
				respObj.putInt(cartasStr[i]+cartasStrCmp[1],cartas[i].Naipe());
				respObj.putInt(cartasStr[i]+cartasStrCmp[2],cartas[i].Baralho());
			}
			sfs.send( new ExtensionRequest("bater", respObj, sfs.lastJoinedRoom) ); 
		}
		/** Função que alerta que o usuário não bateu. */
		private function naoBateu():void{
			container.showGamePopUp("notify", "Você não bateu! Sequência de cartas errada.", container.removeGamePopUp);
		}
		/** Função que mostra o usuário que bateu. */
		private function bateu(params:ISFSObject):void{
			jogoIniciado = false;
			var mensagem:String;
			desativarCartas();
			
			if ( sfs.mySelf.playerId==params.getInt("ganhador") ){
				mensagem = "Você é o GANHADOR. ";
			}
			else{
				mensagem = "O jogador "+params.getInt("ganhador")+" é o ganhador";
			}
			container.showGamePopUp("notify", mensagem, container.removeGamePopUp );	

			if ( sfs.mySelf.playerId!=params.getInt("ganhador") ){
				recebeCartasGanhador(params);
			}

		}
		/** Função que atualiza o número de jogadores que é apresentado
		 *  ao dono da sala antes do início do jogo. */
		private function atualizaNumeroJogadores(params:ISFSObject):void{
			var message:String;
			if (sfs.mySelf.playerId==1){
				nplayers = params.getInt("nplayers");
				container.removeGamePopUp();
				message = "Iniciar jogo\nJogadores = " + nplayers;
				container.showGamePopUp("waitOwner", message, pedeInicioPartida)
			}
		}
		/** Função executada quando cliente recebe o comando de atualização 
		 *  do monte de descarte. */
		private function atualizaDescarte(params:ISFSObject):void{
			sfs.send( new ExtensionRequest("estouVivo", new SFSObject(), sfs.lastJoinedRoom) );
			
			var valor:int = params.getInt("valor");
			var naipe:int = params.getInt("naipe");
			var baralho:int = params.getInt("baralho");

			cartaDoDescarte.setCarta(valor,naipe,baralho);
			cartaDescarteMC.gotoAndStop((cartaDoDescarte.Naipe()+1)+"-"+(cartaDoDescarte.Valor()+1));
			
			if ( jogadorDaVez == sfs.mySelf.playerId ){ /* Se é o jogador da vez então tem */
				jogadorDaVez = params.getInt("t");      /* que reativar as cartas.         */
				ativarCartas();                         
			}
			else {
				jogadorDaVez = params.getInt("t");
				setTurno();
			}
			var msg:TextField = mensagemMC.texto as TextField;
			msg.text = "Vez do jogador "+jogadorDaVez;

			//sfs.send( new ExtensionRequest("log", new SFSObject(), sfs.lastJoinedRoom) );
		}
		/** Função para alterar de jogador para espectador caso o jogo já tenha iniciado. */
		public function setEspectador(params:ISFSObject):void{
			container.removeGamePopUp();
			//container.removeGamePopUp();
			iAmSpectator = true;
			desativarCartas();
			sfs.send( new PlayerToSpectatorRequest() );
		}
		/** Função que mostra as cartas do jogador ganhador */ 
		private function recebeCartasGanhador(params:ISFSObject):void{
			var cartasStr:Array = ["c1","c2","c3","c4","c5","c6","c7","c8","c9"];
			var cartasStrCmp:Array = ["v","n","b"];
			var valor:int;
			var naipe:int;
			var baralho:int;
			
			for (var i:int = 0; i < 9; i++){ 
				valor = params.getInt(cartasStr[i]+cartasStrCmp[0]);
				naipe = params.getInt(cartasStr[i]+cartasStrCmp[1]);
				baralho = params.getInt(cartasStr[i]+cartasStrCmp[2]);
				cartas[i] = new Carta(valor, naipe, baralho);
				var carta_sel:MovieClip = cartasGanhadorMC["cartaG"+i] as MovieClip;
				carta_sel.gotoAndStop((naipe+1)+"-"+(valor+1));
			}
			cartasGanhadorMC.visible=true;
		}
		/** Função que trata as requisições enviadas pelo servidor ao cliente. */ 
		public  function onExtensionResponse(evt:SFSEvent):void {
			var params:ISFSObject = evt.params.params
			var cmd:String = evt.params.cmd
			
			switch(cmd){
				case "start":
					iniciarJogo(params);
					break
				case "atualizaNJ":
					atualizaNumeroJogadores(params);
					break
				case "cartas":
					recebeCartas(params);
					break
				case "cartaDoMonte":
					recebeCartaDoMonte(params);
					break
				case "atualizaCartaDescarte":
					atualizaDescarte(params);
					break
				case "naoBateu":
					naoBateu();
					break
				case "bateu":
					bateu(params);
					break
				case "jaComecou":
					setEspectador(params);
					break
			}
		}
	}
}